<!DOCTYPE html>
<html lang="en">
  <head>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <meta name="author" content="Zhou Wei <zromyk@163.com>">
  <title>C++11特性</title>
  <link rel="shortcut icon" href="/favicon.ico">
  <link rel="stylesheet" href="/style/pure.css">
  <link rel="stylesheet" href="/style/main.css">
  <link rel="stylesheet" href="https://cdn.staticfile.org/font-awesome/4.7.0/css/font-awesome.css">
  <script src='/style/latest.js?config=TeX-MML-AM_CHTML'></script>
  <script src="https://cdn.bootcss.com/jquery/3.2.1/jquery.min.js"></script>
  <script src='/style/Valine.min.js'></script>
  <link href="https://apps.bdimg.com/libs/highlight.js/9.1.0/styles/default.min.css" rel="stylesheet">
  <script src="https://apps.bdimg.com/libs/highlight.js/9.1.0/highlight.min.js"></script>
  <script>hljs.initHighlightingOnLoad();</script>
  <script src="https://cdn.geogebra.org/apps/deployggb.js"></script>
  <script src="https://cdn1.lncld.net/static/js/2.5.0/av-min.js"></script>
  <script src='/style/readTimes.js'></script>
</head>
<body>
  <div id="menu-background"></div>
  <div id="menu">
    <div class="pure-menu pure-menu-horizontal">
  <div id="menu-block">
    <ul class="pure-menu-list">
      <a class="pure-menu-heading" href="/index.html">ZROMYK</a>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/index.html">主页</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/archive/index.html">归档</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/download/index.html">下载</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/feedback/index.html">反馈</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="/public/about/index.html">关于我</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" href="https://github.com/zromyk"><i class="fa fa-github" style="font-size:32px"></i></a>
</li>

    </ul>
  </div>
</div>

  </div>
  <div id="layout">
    <div class="content">
      <div id="content-articles">
  <h1 id="C++11特性" class="content-subhead">C++11特性</h1>
  <p>
    <span>2021-03-27</span>
    <span><span class="post-category post-category-c">C++</span></span>
    <span id="/public/article/Cpp11特性.html" class="leancloud_visitors" style="display:none" data-flag-title="C++11特性"></span>
  </p>
  <blockquote class="content-quote">
<p>详细介绍 C/C++ 的网站：<a href="http://www.cplusplus.com/info/"><strong>Information on the C++ language</strong></a></p>
</blockquote>
<h3 id="1-long-long">1. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>long long</code></span> 数据类型</h3>
<h3 id="2">2. 列表初始化</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int arr = {0};
int arr{0};

// 列表初始化
vector&lt;int&gt; vi = {0, 1, 2, 3, 4, 5, 6};
// 列表赋值
vector&lt;int&gt; vi;
vi = {0, 1, 2, 3, 4, 5, 6};
</code></span></code></pre>
<h3 id="3-constexpr">3. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 变量</h3>
<p>如果在 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 限定符内定义一个指针，那么 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 只对指针有效，与指针指向的对象无关。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">const int *p = nullptr;
constexpr int *q = nullptr;
</code></span></code></pre>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p</code></span> 是一个指向 <strong>整型常量</strong> 的指针</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>q</code></span> 是一个指向 <strong>整数(整型常量表达式)</strong> 的 <strong>常量</strong> 指针</p>
<h3 id="4-constexpr">4. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 函数</h3>
<p>函数的返回类型 及 所有形参的类型都是字面值类型，而且函数体内必须 有且仅有一条 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>return</code></span> 语句。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">constexpr int new_sz() { return 42; }
constexpr int foo = new_sz();
</code></span></code></pre>
<p>允许 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 函数的返回类型是一个 <u>非常量</u>，如果 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 函数的实参时常量表达式，则返回值也是常量表达式。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">constexpr size_t scale(sizr_t cnt) { return new_sz() * cnt; }

int arr[scale(2)];   // 正确，scale(2) 是常量表达式

int i = 2;
int arr[scale(i)];   // 错误，scale(i) 不是常量表达式
</code></span></code></pre>
<h3 id="5-constexpr">5. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 构造函数</h3>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 构造函数可以声明成 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>=default</code></span> 的形式，或者是删除函数的形式。否则 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 构造函数就必须符合构造函数的要求（意味着不能有返回语句），又符合 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 函数的要求（意味着他能拥有的唯一可执行语句就是返回语句），因此，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 构造函数体内一般是空着的。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class Debug {
public:
    constexpr Debug(bool b = true): hw(b), io(b), other(b) {}
    constexpr Debug(bool h, bool i, bool o): hw(h), io(i), other(o) {}
    constexpr bool any() { return hw || io || other; }
    ...
private:
    bool hw;
    bool io;
    bool other;
}
</code></span></code></pre>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 构造函数必须初始化所有数据成员，初始值或者使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 构造函数，或者是一条常量表达式。</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 构造函数用于生成 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 对象以及 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 函数的参数或返回类型：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">constexpr Debug io_sub(false, true, false);
// constexpr Debug(bool h, bool i, bool o): hw(h), io(i), other(o) {}
// constexpr bool any() { return hw || io || other; }
if (Debug.any()) {  // 等价于 if (true)
    cerr &lt;&lt; &quot;...&quot; &lt;&lt; endl;
}
// constexpr Debug(bool b = true): hw(b), io(b), other(b) {}
constexpr Debug prod(false);
if (Debug.any()) {  // 等价于 if (false)
    cerr &lt;&lt; &quot;...&quot; &lt;&lt; endl;
}
</code></span></code></pre>
<h3 id="6-using">6. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>using</code></span> 类型别名</h3>
<p>用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>using</code></span> 进行别名声明：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">using SI = Sales_item;
SI intem; // 等价于 Sales_item intem;

// 用 suing 简化多维数组的指针
using int_array = int[4];
typedef int int_array[4]; // 等价的 typedef 声明
</code></span></code></pre>
<h3 id="7-auto">7. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>auto</code></span> 类型说明符</h3>
<p>（1）当引用被用作初值时，真正参与初始化的是引用对象的值，编译器将 <strong>引用对象</strong> 的类型作为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>auto</code></span> 的类型。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int i = 0, &amp;r = i;
auto a = r; // a 是一个整型
</code></span></code></pre>
<p>（2）<strong><span style="overflow-x: auto; max-width:100%; display:inline;"><code>auto</code></span> 一般会忽略掉顶层 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>const</code></span>，底层 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>const</code></span> 将会被保留下来</strong>，当作初始值。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">const int ci = i, &amp;cr = ci;
auto b = ci;    // 整型 ( ci 的顶层 const 被忽略掉了 )
auto c = cr;    // 整型
auto d = &amp;i;    // 指向 整型 的指针
auto e = &amp;ci;   // 指向 整型常量 的指针

const auto f = ci;  // ci 的推演是 int, f 是 const int
</code></span></code></pre>
<p>将引用的类型设置为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>auto</code></span>，此时原来的初始化规则任然使用：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">auto &amp;g = ci;       // 正确，g 是一个常量引用
auto &amp;h = 42;       // 错误
const auto &amp;j = 42; // 正确
</code></span></code></pre>
<p>（3）设置一个类型为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>auto</code></span> 的引用时，初始值汇总的顶层常量属性仍然保留。</p>
<p>切记，符号 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>*</code></span> 和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>&amp;</code></span> 只从属于某个声明符，而非基本数据类型的一部分，因此初始化值必须使用一种类型：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">auto k = ci, &amp;l = i;    // ci 是整型常量，i 是整型，此时推断 auto 为 const int
auto &amp;m = ci, *p = &amp;ci; // ci 是整型常量，此时推断 auto 为 const int

// error: 'auto' deduced as 'int' in declaration of 'n' and deduced as 'const int' in declaration of 'p2'
auto &amp;n = i, *p2 = &amp;ci; // i 是整型，ci 是整型常量，推断 n 为 int，p2 为 const int
</code></span></code></pre>
<h3 id="8-decltype">8. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>decltype</code></span> 类型指示符</h3>
<p>作用：选择并返回操作数的数据类型。编译期分析表达式并得到他的类型，却不实际计算表达式的值。</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>decltype</code></span> 处理顶层 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>const</code></span> 和引用的方式与 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>auto</code></span> 有些不同。</p>
<p>如果 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>decltype</code></span> 使用的表达式是一个变量，则 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>decltype</code></span> 返回该变量的类型（包括顶层 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>const</code></span> 和引用在内）</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">const int ci = 0, &amp;cj = ci;
decltype(ci) x = 0; // const int
decltype(cj) y = x; // const int&amp;
decltype(cj) z;     // const int&amp;, 错误，引用必须初始化

// decltype 能够返回一个表达式结果对应的类型
int i = 42, *p = &amp;i, &amp;r = i;
decltype(r + 0) b;  // 正确，int
decltype(*p) c;     // 错误，int&amp;，必须初始化

// decltype 的表达式如果加上了括号变量，结果将是引用
decltype((i)) d;    // 错误，int&amp;，必须初始化
decltype(i) e;      // 正确
</code></span></code></pre>
<blockquote class="content-quote">
<p>注意：<span style="overflow-x: auto; max-width:100%; display:inline;"><code>decltype((表达式))</code></span> 的结果永远是 <strong>引用</strong>，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>decltype(表达式)</code></span> 只有当结果本身是引用的时候才是引用。</p>
</blockquote>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int arr[] = {1, 2, 3, 4, 5};
decltype(arr) *arrPtr() {
    return &amp;arr;
}
</code></span></code></pre>
<h3 id="9-for">9. 范围 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>for</code></span> 语句</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">for (declaration : expression) {
    statement;
}

for (auto c : str) {
    cout &lt;&lt; c &lt;&lt; endl;
}

for (auto beg = v.begin(), end = v.end(); beg != end; ++ beg) {
    ... // 在里面对 vector 等顺序容器进行删除和添加操作将造成 end 无效
}
</code></span></code></pre>
<h3 id="10">10. 类内初始值</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">struct Data{
    std::string bookNo;
    unsigned units_sold = 0;
    double revenue = 0.0;
    double revenue1 = 0.0;
    double revenue2 = {0.0};
    double revenue3{0.0};
    // double revenue4(0.0); // 报错
};  // &lt;---- 注意添加分号

// 注意上面的 double revenue(0.0) 将报错
// 而以下代码在 结构体 struct 外都可以正常编译
double revenue1 = 0.0;
double revenue2 = {0.0};
double revenue3{0.0};
double revenue4(0.0);
</code></span></code></pre>
<h3 id="11-vector">11. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>vector</code></span> 对象</h3>
<p>（1）列表初始化 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>vector</code></span> 对象</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">vector&lt;string&gt; v1{&quot;a&quot;, &quot;ab&quot;, &quot;abc&quot;}; // 列表初始化
// 错误 vector&lt;string&gt; v1(&quot;a&quot;, &quot;ab&quot;, &quot;abc&quot;); // 错误
</code></span></code></pre>
<p>（2）不能在 <strong>范围 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>for</code></span> 循环</strong> 内 <strong>添加</strong> 或者 <strong>删除</strong> 元素</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">vector&lt;int&gt; v(10, 0);
for (auto &amp;r : v) {
    // v.push_back();   // 禁止这种操作 ！！！
}
// 原因等价于下面的情况：
for (auto sta = v.begin(), end = v.end(); sta != end; ++sat) {
    // v.push_back();   // 禁止这种操作 ！！！
    // 此操作会导致 end 无效
}
</code></span></code></pre>
<p>（3）使用数组初始化 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>vector</code></span> 对象</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int int_arr[] = {0, 1, 2, 3, 4, 5};
// 下面两种初始化方法都正确
vector&lt;int&gt; ivec(begin(int_arr), end(int_arr));
vector&lt;int&gt; ivec(int_arr, int_arr + 6); // 添加 int_arr[0] ... int_arr[5]
</code></span></code></pre>
<h3 id="12-const_interator-interator">12. 常量迭代器 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>const_interator</code></span> 类型和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>interator</code></span> 的返回值</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">auto it = v.cbegin();
auto it = v.cend();

auto it = v.begin();
auto it = v.end();
</code></span></code></pre>
<h3 id="13-auto-decltype">13. 使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>auto</code></span> 和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>decltype</code></span> 的简化声明</h3>
<p>主要用于尽可能地避免在数组前面加上一个指针类型.</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">for (auto p = arr; p != arr + 3; ++p) {
    ...
}

for (auto p = begin(arr); p != end(arr); ++p) {
    ...
}
</code></span></code></pre>
<h3 id="14-initializer_list">14. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>initializer_list</code></span> 形参</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code>initializer_list&lt;T&gt; lst;
initializer_list&lt;T&gt; lst{a, b, c, ...};
lst2(lst);
lst2 = lst1;
lst.size();
lst.begin();
lst.end();
</code></span></code></pre>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>initializer_list</code></span> 对象的元素是常量值，无法改变 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>initializer_list</code></span> 对象中的元素的值.</p>
<h3 id="15">15. 列表初始化返回值</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">vector&lt;string&gt; func() {
    return {&quot;val1&quot;, &quot;val2&quot;, &quot;val3&quot;};
}
</code></span></code></pre>
<h3 id="16">16. 使用尾置返回类型</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">auto func() -&gt; int(*)[10];
</code></span></code></pre>
<h3 id="17-default">17. 使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>= default</code></span> 显式生成默认构造函数</h3>
<p>使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>= default</code></span> 显式生成的默认构造函数，将和未定义其他构造函数时编译器生成的默认构造函数相同。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class Data {
    Data() = default;
    Data(int data);
}
</code></span></code></pre>
<h3 id="18">18. 委托构造函数</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class Sales_data {
public:
    // 非委托构造函数使用对应的实参初始化成员
    Sales_data(std::string s, unsigned cnt, double price):
        bookNo(s), units_sold(cnt), revenue(cnt * price) {}

    // 其余构造函数全部委托给另一个构造函数
    Sales_data(): Sales_data(&quot; &quot;, 0, 0) {}
    Sales_data(std::string s): Sales_data(s, 0, 0) {}
}
</code></span></code></pre>
<h3 id="19-string">19. 用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>string</code></span> 对象处理文件名</h3>
<h3 id="20-cbegin-cend">20. 容器的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>cbegin</code></span> 和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>cend</code></span> 函数</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// C++11 以前
list&lt;string&gt;::iterator          it1 = a.begin();
list&lt;string&gt;::const_iterator    it2 = a.begin();
// C++11
auto it3 = a.begin();   // 仅当 a 是 const 时，it3 是 const_iterator
auto it4 = a.cbegin();  // it4 是 const_iterator
</code></span></code></pre>
<h3 id="21-swap">21. 容器的非成员函数 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>swap</code></span></h3>
<p>C++11 即提供成员函数版本的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>sawp</code></span>，也提供非成员版本的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>swap</code></span>（早期标准库只提供成员函数版本的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>swap</code></span>）</p>
<p>非成员函数版本的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>swap</code></span> 在泛型编程中具有重要作用，统一使用非成员函数版本的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>swap</code></span> 是一个好习惯。</p>
<h3 id="22-insert">22. 容器 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>insert</code></span> 成员的返回类型</h3>
<p>C++11 中，接受元素 <strong>个数或范围</strong> 的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>insert</code></span> 函数返回指向第一个新加入元素的迭代器。（在旧版本的标准库中，这些操作返回 void）如果范围为空，不插入任何元素，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>insert</code></span> 操作会将 <strong>第一个参数</strong> 返回。</p>
<h3 id="23-emplace">23. 容器的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>emplace</code></span> 成员函数</h3>
<p>C++11 中引入了三个新成员（<span style="overflow-x: auto; max-width:100%; display:inline;"><code>emplace_front, emplace, emplace_back</code></span>）这些操作构造不是拷贝元素。这些操作分别对应 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>push_front, insert, push_back</code></span>，允许我们将元素防止在容器头部，一个指定位置或容器尾部。</p>
<p>当调用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>push_front, insert, push_back</code></span> 成员函数时，我们将元素类型的对象传递给他们，这些对象被拷贝到容器中。</p>
<p>当我们调用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>emplace_front, emplace, emplace_back</code></span> 成员函数时，则是将参数传递给 <strong>元素类型的构造函数</strong>。<span style="overflow-x: auto; max-width:100%; display:inline;"><code>emplace</code></span> 使用这些参数在容器管理的内存空间中直接构造元素。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// 在 c 的末尾构造一个 NameData 对象
c.emplace_back(&quot;String&quot;, 1, 2);         // 使用三个参数的 NameData 构造函数
// c.push_back(&quot;String&quot;, 1, 2);         // 错误，没有三个参数的 push_back 成员函数
c.push_back(NameData(&quot;String&quot;, 1, 2));  // 正确，创建一个临时的 NameData 对象传递给 push_back
</code></span></code></pre>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>emplace</code></span> 函数的参数根据 元素类型而变化，参数必须与元素类型的构造函数相匹配。</p>
<h3 id="24-shrink_to_fit">24. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>shrink_to_fit</code></span> 成员函数</h3>
<p>C++11 中，可以调用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>shrink_to_fit</code></span> 函数来要求 <strong><span style="overflow-x: auto; max-width:100%; display:inline;"><code>vector, deque, string</code></span></strong> 返回不需要的内存空间。此函数指出我们不需要多余的内存空间，但是具体的实现可以忽略此请求，即调用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>shrink_to_fit</code></span> 成员函数并不一定会返回内存空间。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">v.shrink_to_fit();
</code></span></code></pre>
<h3 id="25-string">25. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>string</code></span> 的数值转换函数</h3>
<p>C++11 中，引入了多个数值转化函数，可以实现数值数据与标准库 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>string</code></span> 之间的转换：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int i = 41;
string s = to_string(i);
double d = stod(s);

string s2 = &quot;pi = 3.14&quot;;
// 转换 s2 中以数字开始的第一个子串，结果为 d = 3.14
d = stod(s2.substr(s2.find_first_of(&quot;+-.0123456789&quot;)));
</code></span></code></pre>
<blockquote class="content-quote">
<p>如果 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>string</code></span> 不能转化为一个数值，这些函数将会抛出一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>invalid_argument</code></span> 异常。</p>
<p>如果转换得到的数值无法用任何形式来表示，则会抛出一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>out_of_range</code></span> 异常。</p>
</blockquote>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>函数</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>to_string(val)</code></span></td>
<td>一组重载函数，返回数值 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>val</code></span> 的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>string</code></span> 表示。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>stoi(s, p, b)</code></span></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>int</code></span></td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>stol(s, p, b)</code></span></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>long</code></span></td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>stoul(s, p, b)</code></span></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>unsigned long</code></span></td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>stoll(s, p, b)</code></span></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>long long</code></span></td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>stoull(s, p, b)</code></span></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>unsigned long long</code></span></td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>stof(s, p)</code></span></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>float</code></span></td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>stod(s, p)</code></span></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>double</code></span></td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>stold(s, p)</code></span></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>long double</code></span></td>
</tr>
</tbody>
</table></div>
<blockquote class="content-quote">
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>b</code></span> 表示转化所用的基数</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p</code></span> 是 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>size_t</code></span> 指针，用来保存 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>s</code></span> 中第一个非数值字符的下标，默认为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>0</code></span>（表示函数不保存下标）</p>
</blockquote>
<h3 id="26-lambda">26. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 表达式</h3>
<p>一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 表达式表示一个可以调用的代码单元，我们可以将其理解为一个未命名的内联函数。与任何函数类似，一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 具有一个返回类型、一个参数列表和一个函数体。但与函数不同，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 可能定义在函数内部。一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 表达式具有如下形式：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">[capture list](parameter list) -&gt; return type { function body }
</code></span></code></pre>
<ul>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>capture list</code></span>，捕获列表，是一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 所在函数中定义的局部变量的列表</li>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>parameter lsit</code></span> 参数列表</li>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>return type</code></span> 返回类型，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 必须使用尾置返回类型</li>
<li><span style="overflow-x: auto; max-width:100%; display:inline;"><code>function body</code></span> 函数体</li>
</ul>
<p>其中参数列表和返回类型可以忽略。</p>
<h4 id="1-lambda">1. 向 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 传递参数</h4>
<p>与普通函数不同，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 不能有默认参数，一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 调用的实参数目永远与形参数目相等。</p>
<h4 id="2_1">2. 捕获列表</h4>
<h5 id="_1">值捕获</h5>
<p>与传值参数类似，采用值捕获的前提是变量可以拷贝。与参数不同，被捕获的变量的值是在 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 创建时拷贝，而不是调用时拷贝。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">void fcn1()
{
    size_t v1 = 42; // 局部变量
    // 将 v1 拷贝到名为 f 的可调用对象
    auto f = [v1]{ return v1; };
    v1 = 0;
    auto j = f(); // j 为 42，f 保存了我们创建它时 v1 的拷贝
}
</code></span></code></pre>
<p>被捕获的变量的值是在 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 创建时拷贝，因此随后对其修改不会影响到 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 内对应的值。</p>
<h5 id="_2">引用捕获</h5>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">void fcn2()
{
    size_t v1 = 42; // 局部变量
    // 将 v1 拷贝到名为 f 的可调用对象
    auto f2 = [&amp;v1]{ return v1; };
    v1 = 0;
    auto j = f2(); // j 为 0，f 保存 v1 的引用，而非拷贝
}
</code></span></code></pre>
<p>引用捕获与返回引用有着相同的问题和限制。如果我们采用引用方式捕获一个变量，就必须确保被引用对象在 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 执行的时候是存在的。<span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 捕获的都是局部变量，这些变量在函数结束后就不复存在了。</p>
<p>引用拷贝有时候是必要的：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">void biggies(vector&lt;string&gt; &amp;words, 
            vector&lt;string&gt;::size_type sz, 
            ostream &amp;os = cout, char c = '')
{
    for_each(words.begin(), words.end(),
            [&amp;os, c](const string &amp;s) { os &lt;&lt; s &lt;&lt; c; });
            // 不能拷贝 ostream 对象，只能引用
}
</code></span></code></pre>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th><span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 捕获列表</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>[]</code></span></td>
<td>空捕获列表</td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 不能使用其所在函数中的变量。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>[names]</code></span></td>
<td>names 是一个逗号分隔的名字列表，为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 所在函数的局部变量</td>
<td>默认情况下为这些变量都会被 <strong>拷贝</strong>，可以在 name 前面 <strong>加 &amp; 采用引用捕获</strong>。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>[&amp;]</code></span></td>
<td>隐式捕获列表，采用引用捕获方式</td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 体中所有使用的来自函数的实体都采用 <strong>引用</strong> 方式。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>[=]</code></span></td>
<td>隐式捕获列表，采用值捕获方式</td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 将 <strong>拷贝</strong> 所使用的的来自函数体的实体的值。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>[&amp;, identifier]</code></span></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>identifier</code></span> 是个逗号分隔的列表，包含 0 个或多个来自函数的变量。</td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>identifier</code></span> 中的变量采用 <strong>值</strong> 捕获方式，而其他任何隐式捕获的方式都采用<strong>引用</strong>捕获方式。<span style="overflow-x: auto; max-width:100%; display:inline;"><code>identifier</code></span> 中的名字前面都 <strong>不能</strong> 使用 &amp;。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>[=, identifier]</code></span></td>
<td></td>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>identifier</code></span> 中的变量采用 <strong>引用</strong> 捕获方式，而其他任何隐式捕获的方式都采用 <strong>值</strong> 捕获方式。<span style="overflow-x: auto; max-width:100%; display:inline;"><code>identifier</code></span> 中的名字<strong>不能包含 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>this</code></span></strong>，且这些名字前面 <strong>必须</strong> 使用 &amp;。</td>
</tr>
</tbody>
</table></div>
<h3 id="27-lambda">27. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 表达式中的尾置返回类型</h3>
<blockquote class="content-quote">
<p><a href="https://blog.csdn.net/fengbingchun/article/details/63252470">C++/C++11中std::transform的使用</a></p>
</blockquote>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::transform</code></span> 在指定的范围内应用于给定的操作，并将结果存储在指定的另一个范围内。要使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::transform</code></span> 函数需要包含<span style="overflow-x: auto; max-width:100%; display:inline;"><code>&lt;algorithm&gt;</code></span> 头文件。</p>
<p>以下是 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::transform</code></span> 的两个声明，一个是对应于一元操作，一个是对应于二元操作：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">template &lt;class InputIterator, class OutputIterator, class UnaryOperation&gt;
OutputIterator transform (InputIterator first1, InputIterator last1,
                      OutputIterator result, UnaryOperation op);

template &lt;class InputIterator1, class InputIterator2,
    class OutputIterator, class BinaryOperation&gt;
OutputIterator transform (InputIterator1 first1, InputIterator1 last1,
                    InputIterator2 first2, 
                    OutputIterator result, BinaryOperation binary_op);
</code></span></code></pre>
<p>对于一元操作，将 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>op</code></span> 应用于 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>[first1, last1)</code></span> 范围内的每个元素，并将每个操作返回的值存储在以 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>result</code></span> 开头的范围内。给定的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>op</code></span> 将被连续调用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>last1-first1</code></span> 次。<span style="overflow-x: auto; max-width:100%; display:inline;"><code>op</code></span> 可以是函数指针或函数对象或 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 表达式。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">transform(vi.begin(). vi.end(), vi.begin(), 
          [](int i)
          { return i &lt; 0 ? -i : i; })
</code></span></code></pre>
<p>上面的代码可以将 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>vi</code></span> 中的元素求绝对值，并将结果保存在原来位置。在本例中我们传递给 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>transform</code></span> 一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span>，它返回其参数的绝对值。<span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 体是单一的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>return</code></span> 语句，返回一个表达式的结果，我们无须为其制定返回类型，因为可以根据条件运算的结果推测出来。</p>
<p>但是将程序改为看起来等价的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>if</code></span> 语句，就会产生编译错误：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// 错误：不能推断 lambda 的返回类型
transform(vi.begin(). vi.end(), vi.begin(), 
        [](int i)
        { if (i &lt; 0) return -i; else return i; })
</code></span></code></pre>
<p>编译器推断这个版本的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 返回类型为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>void</code></span>，但它返回了一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>int</code></span> 值 。</p>
<p>当我们需要为一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 指定返回类型时，必须使用尾置返回类型。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">transform(vi.begin(). vi.end(), vi.begin(), 
        [](int i) -&gt; int 
        { if (i &lt; 0) return -i; else return i; })
</code></span></code></pre>
<h3 id="28-bind">28. 标准库 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 函数</h3>
<blockquote class="content-quote">
<p><a href="https://ppipp.blog.csdn.net/article/details/84760715?utm_medium=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control&amp;dist_request_id=1328767.24503.16174181854762895&amp;depth_1-utm_source=distribute.pc_relevant_t0.none-task-blog-2%7Edefault%7EBlogCommendFromMachineLearnPai2%7Edefault-1.control">C++ 之std::function()及 std::bind() 学习总结</a></p>
<p><a href="https://blog.csdn.net/qq_42145185/article/details/108509242?utm_medium=distribute.pc_relevant.none-task-blog-baidujs_baidulandingword-0&amp;spm=1001.2101.3001.4242">学习笔记 c++ （函数对象 C++ function对象,C++ bind 解析以及实例）</a></p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 函数定义在头文件 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>functional</code></span> 中。</p>
</blockquote>
<p>使用标准库 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 函数，可以解决向 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>check_size</code></span> 传递一个长参数的问题。</p>
<p>可以将 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 函数看作一个通用函数适配器，它接受一个可调用对象，生成一个新的可调用对象来“适应”原对象的参数列表。</p>
<p>调用  <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 函数的一般形式：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">auto newCallable = bind(callable, arg_list);
</code></span></code></pre>
<p>其中，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>newCallable</code></span> 是一个可调用对象，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>arg_list</code></span> 是一个逗号可分隔的参数列表，对应给定的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>callable</code></span> 的参数，当我们调用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>newCallable</code></span> 时，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>newCallable</code></span> 会调用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>callable</code></span>，并传递给它 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>arg_list</code></span> 中的参数。</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>arg_list</code></span> 中的参数可能包含形如 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>_n</code></span> 的名字，其中 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>n</code></span> 是一个整数。这些参数是 “占位符”，表示 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>newCallable</code></span> 的参数，他们占据了传递给 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>newCallable</code></span> 的参数的位置。（数值 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>n</code></span> 表示生成的可调用对象中参数的位置：<span style="overflow-x: auto; max-width:100%; display:inline;"><code>_1</code></span> 为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>newCallable</code></span> 的第一个参数，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>_2</code></span> 为第二个参数&hellip;）</p>
<h4 id="1-check_size-sz">1. 绑定 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>check_size</code></span> 的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>sz</code></span> 参数</h4>
<blockquote class="content-quote">
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>check_size</code></span> 为一个自定义的函数</p>
</blockquote>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">bool check_size(const string &amp;s, string::size_type sz) {
    return s.size() &gt;= sz;
}

// check6 是一个可调用对象，接受一个 string 类型的参数
// 并用此 string 和值 6 来调用 check_size
auto check6 = bind(check_size, _1, 6);
</code></span></code></pre>
<p>此 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 调用只有一个占位符，表示 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>check6</code></span> 只接受单一参数。</p>
<p>占位符出现在 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>arg_list</code></span> 的一个位置，表示 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>check6</code></span> 的此参数对应 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>chaeck_size</code></span> 的第一个参数。此参数是一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>const string &amp;</code></span>，因此，调用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>check6</code></span> 必须传递给它一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>string</code></span> 类型的参数，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>check6</code></span> 会将此参数传递给 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>check_size</code></span>。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">string s = &quot;hello&quot;;
bool b1 = check6(s); // check6(s) 会调用 check_size(s, 6)
</code></span></code></pre>
<p>使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span>函数，可以将原来基于 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>find_if</code></span> ：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">auto wc = find_if(words.begin(), words.end(), [sz](const string &amp;a){ return a.size() &gt;= sz} );
</code></span></code></pre>
<p>替换为如下形式：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">auto wc = find_if(words.begin(), words.end(), bind(check_size, _1, sz));
</code></span></code></pre>
<blockquote class="content-quote">
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>find_if()</code></span> </p>
<p>同 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>find()</code></span> 一样，为在输入迭代器所定义的范围内查找单个对象的算法，它可以在前两个参数指定的范围内查找可以使第三个参数指定的谓词返回 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>true</code></span> 的第一个对象。谓词不能修改传给它的对象。<span style="overflow-x: auto; max-width:100%; display:inline;"><code>find_if()</code></span> 会返回一个指向被找到对象的迭代器，如果没有找到对象，会返回这个 序列的结束迭代器。</p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>for_each()</code></span> </p>
<p>也是一个模板函数。(关于模板函数可以参考《c++高级编程》，《c++ template》) 第一个参数为迭代器的开始位置，第二个参数为迭代器的末位，也就是迭代器最后一位的下一位。第三个参数为一个函数指针，或者函数对象。</p>
</blockquote>
<h4 id="2-stdplaceholders">2. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::placeholders</code></span></h4>
<blockquote class="content-quote"></blockquote>
<h5 id="placeholders">使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>placeholders</code></span> 名字</h5>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>placeholders</code></span> 为 C++11 的新特性</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">namespace placeholders {
    extern /* unspecified */ _1;
    extern /* unspecified */ _2;
    extern /* unspecified */ _3;
    // ...
}
</code></span></code></pre>
<p>其中<em>1, </em>2, <em>3是未指定的数字对象，用于 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>function</code></span> 的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 中。 </em>1用于代替回调函数中的第一个参数， _2用于代替回调函数中的第二个参数，以此类推。</p>
<p>名字 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>_n</code></span> 都定义在一个名为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>placeholders</code></span> 的命名空间中，而这个命名空间本身定义在 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>std</code></span> 命名空间中。为了使用这些名字，两个命名空间都要写上。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">suing std::placeholders::_1;
// 或者统一使用
using namespace std::placeholders;
</code></span></code></pre>
<h5 id="bind">用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 重拍参数顺序</h5>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// 按单词长度由短至长排序
sort(words.begin(), words.end(), isShorter);
// 按单词长度由长至短排序
sort(words.begin(), words.end(), bind(isShorter, _2, _1));
</code></span></code></pre>
<h5 id="_3">绑定引用参数</h5>
<p>默认情况下，<span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 的那些占位符是 <strong>拷贝</strong> 方式，但是有些时候我们需要用 <strong>引用</strong> 方式绑定参数。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// os 是一个局部变量，引用一个输出流
// c  是一个局部变量，类型为 char
for_each(words.begin(), words.end(), [&amp;os, c](const string &amp;s){ os &lt;&lt; s &lt;&lt; c; });
</code></span></code></pre>
<p>我们可以编写一个函数，完成相同的工作</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">ostream &amp;pring(ostream &amp;os, const string &amp;s, char c) {
    return os &lt;&lt; s &lt;&lt; c;
}
</code></span></code></pre>
<p>但是不能用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 来替代对 os 的捕获（<span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 默认为值捕获，而 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>os</code></span> 不能被拷贝）</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// for_each(words.begin(), words.end(), bind(print, os, _1, ' ')); // 错误，不能拷贝 os
</code></span></code></pre>
<p>当我们希望传递给 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 一个对象而又不拷贝它，就必须使用标准库函数 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>ref</code></span></p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">for_each(words.begin(), words.end(), bind(print, ref(os), _1, ' '));
</code></span></code></pre>
<p>函数 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>ref</code></span> 返回一个对象，包含给定的引用，此对象是可以拷贝的。标准库中还有一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>cref</code></span> 函数，生成一个保存 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>const</code></span> 引用类。</p>
<p>函数 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>ref</code></span> 和函数 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>cref</code></span> 也定义在头文件 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>functional</code></span> 中。</p>
<h5 id="2-stdis_placeholder">2. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::is_placeholder</code></span></h5>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::is_placeholder</code></span> 用于判断T是否为占位符，它有一个成员变量 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>value</code></span>。如果 T 是 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>placeholder</code></span> 类型，value 的值为 1 代表 <em>1，2 代表 </em>2；如果 T 不是，则 value 为 0。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">#include &lt;iostream&gt;     // std::cout, std::boolalpha
#include &lt;functional&gt;   // std::is_placeholder, std::placeholders

int main () {
    using namespace std::placeholders;  // introduces _1

    std::cout &lt;&lt; std::is_placeholder&lt;decltype(_1)&gt;::value &lt;&lt; '\n';  // 1
    std::cout &lt;&lt; std::is_placeholder&lt;decltype(_2)&gt;::value &lt;&lt; '\n';  // 2
    std::cout &lt;&lt; std::is_placeholder&lt;int&gt;::value &lt;&lt; '\n';           // 0

    return 0;
}
</code></span></code></pre>
<h5 id="3-stdis_bind_expression">3. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::is_bind_expression</code></span></h5>
<p>判断是否是 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 表达式，有 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>value</code></span> 成员，返回值是 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>true</code></span> 或 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>false</code></span>，其示例如下：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">#include &lt;iostream&gt;     // std::cout, std::boolalpha
#include &lt;functional&gt;   // std::bind, std::plus, std::placeholders, std::is_bind_expression

int main () {
    using namespace std::placeholders;  // introduces _1
    auto increase_int = std::bind(std::plus&lt;int&gt;(), _1, 1);

    std::cout &lt;&lt; std::boolalpha;
    std::cout &lt;&lt; std::is_bind_expression&lt;decltype(increase_int)&gt;::value &lt;&lt; '\n'; // true

    return 0;
}
</code></span></code></pre>
<h3 id="29">29. 关联容器的初始化列表</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">map&lt;string, size_t&gt; word_count; // 空容器
// 列表初始化
set&lt;string&gt; exclude = {&quot;and&quot;, &quot;or&quot;, /*, .... ,*/ &quot;not&quot;};
map&lt;string, string&gt; authors = { {&quot;Joyce&quot;, &quot;James&quot;}, {&quot;Austen&quot;, &quot;Jane&quot;}};
</code></span></code></pre>
<h3 id="30-pair">30. 列表初始化 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>pair</code></span> 的返回类型</h3>
<blockquote class="content-quote">
<p><a href="https://blog.csdn.net/sevenjoin/article/details/81937695">C++ pair的基本用法总结（整理）</a></p>
<p><span style="overflow-x: auto; max-width:100%; display:inline;"><code>pair</code></span> 为标准库类型，定义在头文件 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>utility</code></span> 中。</p>
</blockquote>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">pair&lt;string, int&gt; process(vector&lt;string&gt;, &amp;v) {
    if (!v.empty) return { v.back(), v.back().size() }; // 列表初始化
    else          return pair&lt;string, int&gt;();           // 隐式构造返回值
}
</code></span></code></pre>
<h3 id="31-pair">31. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>pair</code></span> 的列表初始化</h3>
<p>对一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>map</code></span> 容器进行 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>insert</code></span> 操作时，记住元素必须是 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>pair</code></span> 类型。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">word_cont.insert( {word, 1} );
word_cont.insert( make_pair(word, 1) );
word_cont.insert( pair&lt;string, int&gt;(word, 1) );
word_cont.insert( map&lt;string, int&gt;::valut_type(word, 1) );
</code></span></code></pre>
<h3 id="32">32. 无序容器</h3>
<p>C++11 新标准定义了 4 个无序关联容器，这些容器不是使用比较运算符来组织元素，卫视使用一个哈希函数和关键字的类型 == 运算符。</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>无序容器</th>
<th>功能</th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>unordered_map</code></span></td>
<td>存储键值对 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>&lt;key, value&gt;</code></span> 类型的元素，其中各个键值对键的值不允许重复，且该容器中存储的键值对是无序的。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>unordered_multimap</code></span></td>
<td>和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>unordered_map</code></span> 唯一的区别在于，该容器 <strong>允许存储多个键相同的键值对</strong>。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>unordered_set</code></span></td>
<td>不再以键值对的形式存储数据，而是直接存储数据元素本身（当然也可以理解为，该容器存储的全部都是键 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>key</code></span> 和值 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>value</code></span> 相等的键值对，正因为它们相等，因此只存储 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>value</code></span> 即可）。另外，该容器存储的元素不能重复，且容器内部存储的元素也是无序的。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>unordered_multiset</code></span></td>
<td>和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>unordered_set</code></span> 唯一的区别在于，该容器 <strong>允许存储值相同的元素</strong>。</td>
</tr>
</tbody>
</table></div>
<h4 id="395">管理桶 395</h4>
<p>无序容器在存储上组织为一组桶，每个桶保存零个或多个元素。无序容器使用一个哈希函数将元素映射到桶。</p>
<h3 id="33">33. 智能指针</h3>
<h4 id="auto_ptr">auto_ptr</h4>
<p>http://www.cplusplus.com/reference/memory/auto_ptr/</p>
<h4 id="unique_ptr">unique_ptr</h4>
<p>http://www.cplusplus.com/reference/memory/unique_ptr/</p>
<h4 id="shared_ptr">shared_ptr</h4>
<p>http://www.cplusplus.com/reference/memory/shared_ptr/</p>
<p>当两个对象相互使用一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>shared_ptr</code></span> <strong>成员变量</strong> 指向对方，会造成循环引用，使引用计数失效，从而导致内存泄漏。</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>成员函数</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.swap()</code></span></td>
<td>交换两个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>shared_ptr</code></span> 对象(即交换所拥有的对象)</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.reset()</code></span></td>
<td>放弃内部对象的所有权或拥有对象的变更，会引起原有对象的引用计数的减少</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.get()</code></span></td>
<td>返回内部对象(指针)，由于已经重载了()方法, 因此和直接使用对象是一样的</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.use_count()</code></span></td>
<td>返回引用计数的个数</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.unique()</code></span></td>
<td>返回是否是独占所有权( <span style="overflow-x: auto; max-width:100%; display:inline;"><code>use_count</code></span> 为 1 )</td>
</tr>
</tbody>
</table></div>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>非成员函数</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>make_shared&lt;T&gt;(args)</code></span></td>
<td>分配并构造一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>T</code></span> 类型的对象，并将参数传递给它的构造函数。<br />并返回一个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>shared_ptr&lt;T&gt;</code></span> 类型的对象，该对象拥有并存储指向它的指针 (使用计数为1)。<br />这个函数使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>::new</code></span> 为对象分配存储空间。</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>allocate_shared&lt;T&gt;(args)</code></span></td>
<td>接受分配器作为参数，并使用它来分配存储。</td>
</tr>
</tbody>
</table></div>
<h4 id="weak_ptr">weak_ptr</h4>
<p>http://www.cplusplus.com/reference/memory/weak_ptr/</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>成员函数</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.swap()</code></span></td>
<td>交换两个 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>shared_ptr</code></span> 对象(即交换所拥有的对象)</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.reset()</code></span></td>
<td>放弃内部对象的所有权或拥有对象的变更，会引起原有对象的引用计数的减少</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.use_count()</code></span></td>
<td>返回引用计数的个数</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.expired()</code></span></td>
<td>检测指针是否过期</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>p.lock()</code></span></td>
<td>获取其对应的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>shared_ptr</code></span> 对象</td>
</tr>
</tbody>
</table></div>
<h3 id="34">34. 动态分配对象</h3>
<h4 id="_4">列表初始化</h4>
<p>默认情况下，动态分配对象是默认初始化的。内置类型或组合类型的对象的值将是未知的，类类型对象将用默认构造函数进行初始化：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int *pi = new int;          // pi 指向一个未知值（未初始化的）int
string *ps = new string;    // 初始化为空 string
</code></span></code></pre>
<p>使用直接初始化方式来初始化一个动态分配对象，传统构造函数初始化类类型对象：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int *pi = new int(0);       // 初始化为 0
int *pi2 = new int();       // 初始化为 0
string *ps = new string(10, '0');
</code></span></code></pre>
<p>列表初始化：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">vector&lt;int&gt; *pv = new vector&lt;int&gt;{0, 1, 2, 3, 4, 5, 6};
</code></span></code></pre>
<h4 id="auto">auto 和动态分配</h4>
<p>如果我们提供了一个括号包围的初始化器，就可以使用 auto 从此初始化器来推断我们想要分配的对象的类型。</p>
<p>但是由于编译器要用初始化器的类型来推断要分配的类型，只有当括号中仅有单一初始化器时才可以使用 auto。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">auto p1 = new auto(obj);        // p 指向一个与 obj 类型相同的对象，该对象用 obj 进行初始化
// auto p2 = new auto{a, b, c}; // 错误：括号中只能有单个初始化器。
</code></span></code></pre>
<h4 id="const">动态分配 const 对象</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// 分配并初始化一个 const int
const int *pci = new const int(1024);
// 分配并默认初始化一个 const 的空 string
const string *pcs = new const string;
</code></span></code></pre>
<p>类似其他任何 const 对象，一个动态分配的 const 对象必须进行初始化。对于一个定义了 <strong>默认构造函数</strong> 的类类型，其 const 动态对象可以使隐式初始化，而其他类型对象就必须显式初始化。</p>
<h3 id="35-for">35. 范围 for 语句不能以用于动态分配数组</h3>
<h3 id="36">36. 动态分配数组的列表初始化</h3>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int *pi = new int[6]{0, 1, 2, 3, 4, 5};
string *ps = new string[6]{&quot;0&quot;, &quot;1&quot;, &quot;2&quot;, &quot;3&quot;, &quot;4&quot;, &quot;5&quot;};
</code></span></code></pre>
<h3 id="37-auto">37. auto 不能用于分配数组</h3>
<h3 id="38-allocatoraonstruct">38. allocator::aonstruct 可以使用任意构造函数</h3>
<p><a href="https://blog.csdn.net/st125475466/article/details/48346037">动态数组new、allocate</a></p>
<p><strong>allocate类</strong></p>
<ul>
<li>new 有一些灵活性上的局限，其中一方面表现在它将内存分配和对象构造结合在一起。</li>
<li>当分配大块内存时，我们计划在这块内存上按需构造对象，我们需要将内存分配和对象构造分离。</li>
<li>那些没有默认构造函数的类不能用 new 动态分配数组。</li>
<li>标准库 allocator 类定义在头文件 memory 中，他帮助我们将内存分配和对象构造分离开来。</li>
<li>它提供一种类型感知的内存分配方法，他的分配是原始的、未初始化的。</li>
<li>aloocator 是一个模板，当一个 allocator 对象分配内存时，其根据给定对象类型确定恰当的内存大小和对其位置。</li>
</ul>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">allocator&lt;string&gt; alloc;    // 可分配 string 对象的 allocator 对象
auto const p = alloc.allocate(n);   // 分配 n 个未初始化的 string
</code></span></code></pre>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>allocator 操作</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>allocator&lt;T&gt; a</code></span></td>
<td>定义名为 a 的 allocator 对象，它可以为类型为 T 的对象分配内存</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>a.allocate(n)</code></span></td>
<td>分配一段原始的、未构造的内存，保存 n 个类型为 T 的对象</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>a.deallocate(p, n)</code></span></td>
<td>释放从 T* 指针 p 中地址开始的内存，这块内存保存了 n 个类型为T的对象<br />p 必须是一个先前有 allocate 返回的指针，且 n 必须是 p 创建时所要求的大小<br />在调用 deallocate 之前，用户必须对每个在这块内存中创建的对象调用 destory</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>a.construct(p,args)</code></span></td>
<td>p 必须为一个类型为 T* 的指针，指向一块原始内存<br />args 被传递给类型为 T 的构造函数，用来在 p 指向的内存中构造一个对象</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>a.destroy(p)</code></span></td>
<td>p 为 T* 类型的指针，此算法对 p 指向的对象执行析构函数</td>
</tr>
</tbody>
</table></div>
<p><strong>allocator 分配未构造的内存</strong></p>
<ul>
<li>
<p>allocator 分配的内存时未构造的，我们需要再次内存中构造对象</p>
</li>
<li>
<p>construct 函数接受一个指针和零个或多个额外参数，在指定位置构造一个函数</p>
</li>
</ul>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">auto q = p; // q 指向最后构造的元素之后的位置
alloc.construct(q++);           // *q 为空字符
alloc.construct(q++, 10, 'c');  // *q 为 cccccccccc
alloc.construct(q++, &quot;hello&quot;);  // *q 为 hello
</code></span></code></pre>
<ul>
<li>
<p>在未构造对象的情况下使用原始内存是错误的</p>
</li>
<li>
<p>当用完对象后，要对每个构造的对象用 destroy 函数销毁他们</p>
</li>
</ul>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">while (q != p)
    alloc.destory(--q); // 释放我们真正构造的 string
</code></span></code></pre>
<ul>
<li>
<p>我们只能对真正构造了的元素进行 destroy</p>
</li>
<li>
<p>一旦元素被销毁，可以重新使用这块内存保存其它的 T</p>
</li>
<li>
<p>也可以将内存归还给系统，释放内存通过调用 deallocate 来完成</p>
</li>
</ul>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">alloc.deallocate(p, n);
</code></span></code></pre>
<p><strong>拷贝和填充未初始化内存的算法</strong></p>
<ul>
<li>标准库为 allocator 类定义了两个伴随算法，在未初始化的内存中创建对象，它们都定义在 memory 头文件中</li>
<li>这些函数在给定目的位置创建元素，而不是由系统分配内存给他们</li>
<li>返回一个指针，指向最后一个构造元素之后的位置</li>
</ul>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th>allocator 算法</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>uninitialized_copy(b, e, b2)</code></span></td>
<td>从迭代器 b 和 e 指出的输入范围中拷贝元素到迭代器 b2 指定的未构造原始内存中 b2 指向的内存必须足够大，能容纳输入序列中元素的拷贝</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>uninitialized_copy(b, n, b2)</code></span></td>
<td>从迭代器 b 指向的元素开始，拷贝 n 个元素到 b2 开始的内存中</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>uninitialized_fill(b, e, t)</code></span></td>
<td>从迭代器 b 和 e 指定的原始内存范围中创建对象，对象的值均为 t的拷贝</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>uninitialized_fill(b, n, t)</code></span></td>
<td>从迭代器 b 指向的内存开始创建 n 个对象，b 必须指向足够大的未构造的原始内存，能够容纳给定数量的对象</td>
</tr>
</tbody>
</table></div>
<p>举例：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// 分配比 vi 中元素所占空间大一倍的动态内存
auto p = alloc.allocate(vi.size() * 2);
// 通过拷贝 vi 中的元素来构造从 p 开始的元素
auto q = uninitialized_copy(vi.begin(), vi.end(), p);
// 将剩余元素初始化为 42
uninitialized_fill_n(q, vi.size(), 42);
</code></span></code></pre>
<h3 id="39-default">39. 将 =default 用于拷贝控制成员</h3>
<p>通过拷贝控制成员定义为 =default 来显式的要求编译器生成合成的版本。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class Sales_data {
public:
    // 拷贝控制成员；使用 default
    Sales_data() = default;
    Sales_data(const Sales_data &amp;) = default;
    Sales_data &amp; operator = (const Sales_data &amp;);
    ~Sales_data() = default;
};
Sales_data &amp; Sales_data::operator=(const Sales_data &amp;) = default;
</code></span></code></pre>
<ul>
<li>当我们在类内使用 =default 修饰成员的声明时，合成的函数将隐式的声明为内联的（就像任何其他类内的声明的成员函数一样）。如果我们不希望合成的成员函数是内联函数，应该只对成员的类外定义使用 =default 。</li>
<li>我们只能对具有合成版本的成员函数使用 =default （即，默认构造函数或拷贝控制成员）</li>
</ul>
<h3 id="40-delete">40. 使用 =delete 阻止拷贝类对象</h3>
<blockquote class="content-quote">
<p>大多数类应该定义默认构造函数、拷贝构造函数和拷贝赋值运算符，无论是显式的还是隐式的。</p>
<p>但对于某些类来说，这些操作是没有合理意义的。在这种情况下，定义类时必须采用某种机制阻止拷贝或赋值。例如 iostream 类阻止了拷贝，避免多个对象写入或读取相同的 IO 缓冲。</p>
</blockquote>
<p>C++11 中，我们可以将拷贝构造函数和拷贝赋值运算符定义为 <strong>删除的函数</strong> 来阻止拷贝。</p>
<p>删除函数：虽然我们声明了它，但不能以任何方式使用它。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class NoCopy {
public:
    NoCopy() = default;                             // 使用合成的默认构造函数
    NoCopy(const NoCopy &amp;) = delete;                // 阻止拷贝
    NoCopy &amp; operator=(const NoCopy &amp;) = delete;    // 阻止赋值
    ~NoCopy() = default;
};
</code></span></code></pre>
<ul>
<li>与 =default 函数不同，=delete 必须出啊现在函数第一次声明的时候。</li>
<li>与 =default 的另一个不同之处，=delete 可以对任何函数使用（析构函数除外）</li>
</ul>
<h4 id="_5">析构函数不能是删除的成员</h4>
<ul>
<li>我们不能删除析构函数，如果析构函数被删除，就无法销毁此类的对象了。</li>
<li>对于一个删除了析构函数的类型，编译器将不允许定义该类型的变量或创建该类的临时变量。</li>
<li>如果一个类中有某个成员的类型删除了析构函数，我们也不能定义该类型的变量和临时对象。</li>
</ul>
<p>对于删除了析构函数的类型，虽然我们不能定义这种类型的变量或成员，但可以动态分配这种类型的对象。但是，不能释放这些对象：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class NoDtor {
public:
    NoCopy() = default; // 使用合成的默认构造函数
    ~NoCopy() = delete; // 删除析构函数
};

// NoDtor nd; // 错误：NoDtor 的析构函数是删除的
NoDtor *p = new NoDtor(); // 正确，但是我们不能 delete p
// delete p; // 错误：NoDtor 的析构函数是删除的
</code></span></code></pre>
<h3 id="41">41. 用移动类对象代替拷贝类对象</h3>
<p>C++11 中，引入两种机制，以避免 string 的拷贝。</p>
<ul>
<li>第一种，有一些标准库，包括 string 定义了所谓的”移动构造函数“。关于 string 的移动构造函数如何工作的细节，以及有关市县的人和其他细节，都是未公开的。但是我们知道，移动构造函数通常是将资源从给定对象”移动“而不是拷贝到正在创建的对象。而且我们知道标准库保证”移后源“string 都有一个指向 char 数组的指针。可以假定 string 的移动构造函数进行了指针的拷贝（浅拷贝），而不是为字符分配内存空间然后拷贝字符（深拷贝）。</li>
<li>第二种，一个名为 move 的标准库函数，它定义在 utility 头文件中。目前，关于 move 我们需要了解两个关键点。<ul>
<li>首先，当 reallocate 在新内存中构造 string 时，它必须调用 move 来表示希望使用 string 的移动构造函数。如果它罗迪奥了 move 调用，将会使用 string 的拷贝构造函数。</li>
<li>其次，我们通常不为 move 提供一个 sding 声明。当我们调用 move 时，直接调用 std::move 而不是 move</li>
</ul>
</li>
</ul>
<blockquote class="content-quote">
<p>标准库容器、string 和 shared<em>ptr <strong>既支持移动也支持拷贝</strong>。IO 类和 unique</em>ptr 类可以 <strong>移动但不能拷贝</strong>。</p>
</blockquote>
<h3 id="42">42. 右值引用</h3>
<p>为支持移动操作，C++11 标准引入新的引用类型——右值引用。</p>
<p>通过 &amp;&amp; 而不是 &amp; 来获得右值引用。如我们将要看到的，右值引用有一个重要的性质——<strong>只能绑定到一个将要销毁的对象</strong>。因此，我们可以自由地将一个右值引用的资源”移动“到另一个对象中。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int i = 42;
int &amp;r = i;
// int &amp;&amp;rr = i;        // 错误：不能将一个右值引用绑定到一个左值上
// int %r2 = i * 42;    // 错误：i * 42 是一个右值
const int &amp;r3 = i * 42; // 正确：我们可以将一个 const 的引用绑定到一个右值上
int &amp;&amp;rr2 = i * 42;     // 正确：将 rr2 绑定到乘法结果上
</code></span></code></pre>
<h4 id="_6">左值持有，右值短暂</h4>
<p>变量是左值，因此我们不能将一个右值引用直接绑定到一个变量上，及时这个变量是右值引用类型也不行。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int &amp;&amp;rr1 = 42;         // 正确：字面值常量是右值
// int &amp;&amp;rr2 = rr1;     // 错误：表达式 rr1 是左值
</code></span></code></pre>
<h3 id="43-move">43. 标准库 move 函数</h3>
<p>虽然不能将一个右值引用直接绑定到一个左值上，但我们可以显示的将一个左值转换为对应的右值引用类型。</p>
<p>我们可以通过调用一个名为 move 的新标准库函数来获得绑定到左值上的右值引用。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int &amp;&amp;rr3 = std::move(rr1);     // 正确
</code></span></code></pre>
<p>我们可以销毁一个移后源对象，也可以赋予它新值，但不能使用一个移后源对象的值。</p>
<h3 id="44">44. 移动构造函数和移动赋值</h3>
<p>类似拷贝构造函数，移动构造函数的第一个参数是该类类型的一个 <strong>右值引用</strong>。与拷贝构造函数一样，任何额外的参数都必须有默认实参。</p>
<p>移动构造函数必须确保移后源对象处于这样一个状态——销毁他是无害的。</p>
<p>当资源移动完成，源对象必须不再指向被移动的资源——这些资源的所属权已经归属新创建的对象。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">StrVec::StrVec(StrVec &amp;&amp;s) noexcept // 移动操作不应该抛出任何异常
    // 成员初始化器接管 s 中的资源
    : elements(s.elements), first_free(s.first_free), cap(s.cap)
{
    // 令 s 进入这样的状态——对其运行 ** 析构函数 ** 是安全的
    s.elements = s.first_free = s.cap = nullptr;
}
</code></span></code></pre>
<h3 id="45-noexcept">45. 移动构造函数通常应该是 noexcept</h3>
<p>noexcept 是我们承诺函数不抛出异常的一种方法。</p>
<h3 id="46">46. 移动迭代器</h3>
<h3 id="47">47. 引用限定成员函数</h3>
<h3 id="48-function">48. function 类模板</h3>
<h4 id="_7">不同类型可能具有相同的调用形式</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// 普通函数
int add(int i, int j) { return i + j; }
// 函数对象
struct divide {
    int operator()(int i, int j) { return i / j; }
}; // &lt;&lt;== 分号
// lambda 表达式，其产生一个未命名的函数对象类
auto mod = [](int i, int j) { return i % j; }; // &lt;&lt;== 分号
</code></span></code></pre>
<p>用 map 构建从运算符到函数指针映射关系，其中函数接受两个 int，返回一个 int</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">map&lt;string, int(*)(int, int)&gt; binops;

binops.insert({&quot;+&quot;, add}); // 正确，{&quot;+&quot;, add} 是一个 pair
// binops.insert({&quot;/&quot;, divide()}); // 错误，divide 不是一个函数指针
// binops.insert({&quot;%&quot;, mod}); // 错误，mod 不是一个函数指针
</code></span></code></pre>
<p>使用 C++11 新标准库 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>function</code></span> 可以解决上述问题</p>
<div class="pure-table-scrollable"><table class="pure-table pure-table-horizontal">
<thead>
<tr>
<th><span style="overflow-x: auto; max-width:100%; display:inline;"><code>function</code></span> 的操作</th>
<th>描述</th>
</tr>
</thead>
<tbody>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>function&lt;T&gt; f;</code></span></td>
<td>f 是一个用来存储可调用对象的空 function，这些可调用对象的调用形式应该与函数类型 T 相同（即 T 是 retType(args)）</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>function&lt;T&gt; f(nullptr);</code></span></td>
<td>显式地构造一个空 function</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>function&lt;T&gt; f(obj);</code></span></td>
<td>在 f 中存储可调用对象 obj 的副本</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>f</code></span></td>
<td>将 f 作为条件：当 f 含有一个可调用对象时为真，否则为假</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>f(args)</code></span></td>
<td>调用 f 中的对象，参数是 args</td>
</tr>
<tr>
<td><strong>定义为 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>function&lt;T&gt;</code></span> 的成员类型</strong></td>
<td></td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>result_type</code></span></td>
<td>该 function 类型的可调用对象返回的类型</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>argument_type</code></span></td>
<td>当 T 有一个或两个实参时定义的类型。如果 T 只有一个实参，则 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>argument_type</code></span> 是该是参类型的同义词；如果有两个实参，则 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>first_argument_type</code></span> 和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>second_argument_type</code></span> 分别代表两个实参类型。<br />If Args&hellip; is a single type, it is an alias of this single type.<br/>Otherwise, not defined.</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>first_argument_type</code></span></td>
<td>If Args&hellip; is a pack of exactly two types, it is an alias of the first type.<br/>Otherwise, not defined.</td>
</tr>
<tr>
<td><span style="overflow-x: auto; max-width:100%; display:inline;"><code>second_argument_type</code></span></td>
<td>If Args&hellip; is a pack of exactly two types, it is an alias of the second type.<br/>Otherwise, not defined.</td>
</tr>
</tbody>
</table></div>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">function&lt;int(int, int)&gt; f1 = add;
function&lt;int(int, int)&gt; f2 = std::minus&lt;int&gt;();
function&lt;int(int, int)&gt; f3 = [](int i, int j) { return i * j; };
function&lt;int(int, int)&gt; f4 = divide();
function&lt;int(int, int)&gt; f5 = mod;

cout &lt;&lt; f1(4, 2) &lt;&lt; endl; // 6
cout &lt;&lt; f2(4, 2) &lt;&lt; endl; // 2
cout &lt;&lt; f3(4, 2) &lt;&lt; endl; // 8
cout &lt;&lt; f4(4, 2) &lt;&lt; endl; // 2
cout &lt;&lt; f5(4, 2) &lt;&lt; endl; // 0

// 使用 map 来保存运算逻辑，其中的元素可以使函数指针，函数对象，或者 lambda
map&lt;string, function&lt;int(int, int)&gt;&gt; binops = {
    {&quot;+&quot;, add},                                 // 函数指针
    {&quot;-&quot;, std::minus&lt;int&gt;()},                   // 标准库函数对象
    {&quot;*&quot;, [](int i, int j) { return i * j; }},  // 未命名的 lambda
    {&quot;/&quot;, divide()},                            // 用户定义的函数对象
    {&quot;%&quot;, mod}                                  // 命名的 lambda 对象
};

binops[&quot;+&quot;](10, 5);
binops[&quot;-&quot;](10, 5);
binops[&quot;*&quot;](10, 5);
binops[&quot;/&quot;](10, 5);
binops[&quot;%&quot;](10, 5);
</code></span></code></pre>
<h4 id="function">重载的函数与 function</h4>
<p>我们不能直接将重载函数的名字存入 function 类型的对象中：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int add(int i, int j) { return i + j; }
Type add(Type i, Type j) { return i + j; }
map&lt;string, function&lt;int(int, int)&gt;&gt; binops;
// binops.insert( {&quot;+&quot;, add} ); // 错误：无法分辨是哪个 add
</code></span></code></pre>
<p>解决上述二义性问题的一条途径是存储函数指针，而非函数的名字：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int (*fp)(int, int) = add;  // 指针所指的是两个 int 的版本
binops.insert( {&quot;+&quot;, fp} ); // 正确
</code></span></code></pre>
<p>另一种方法是使用 lambda 来消除二义性：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// 正确：使用 lambda 来制定我们希望使用的 add 版本
binops.insert( {&quot;+&quot;, [](int i, int j){ return i + j; } } );
// lambda 明确地传入了两个 int，因此此调用只能明确匹配接受两个 int 的 add 版本
</code></span></code></pre>
<h3 id="49-explicit">49. explicit 类型转换运算符</h3>
<p>类型转换符可能产生以外结果</p>
<p>在实践中，类很少提供类型转换符。对类来说，定义向 bool 的类型转换还是比较普遍的现象。</p>
<p>在 C++ 的早期版本中，如果一个类想定义一个向 bool 的类型转换，则它常常遇到一个问题：bool 是一种算数类型，所以类类型的对象转换成 bool 后就能被用在任何需要算数类型的上下文中。这样的类型转换可能引发意想不到的结果，特别是当 istream 含有向 bool 的类型转换时，下面的代码将编译通过：</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int i = 42;
cin &lt;&lt; i;   // 注意是 cin 不是 cout，实际测试中，编译器会报错
</code></span></code></pre>
<p>这段程序试图将输出运算符作用于输入流，因为 istream 本省并没有定义 &lt;&lt; ，做一本来代码应该产生错误。但是该代码能够使用 istream 的 bool 类型转换符将 cin 转换成 bool，而这个 bool 值将会被提升成 int 并用作内置的左移运算符的左侧运算对象。这样一来提升后的 bool 值，最终会被左移 42 个位置。</p>
<p>为了防止这样的异常情况发生，C++11 新标准引入了显式的类型转换运算符 explicit</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class SmallInt {
public:
    // 编译器不会自动执行这一类型转换
    explicit operator int() const { return val; } // 指出该操作必须显式调用
    // operator int() const { return val; } // 编译器可以隐式地将 SmallInt 对象转换成 int 类型参与计算
    SmallInt(int i = 0) : val(i) {...}
}
</code></span></code></pre>
<blockquote class="content-quote">
<p>https://blog.csdn.net/guoyunfei123/article/details/89003369</p>
</blockquote>
<p>C++ 中的 explicit 关键字只能用于修饰只有一个参数的类构造函数，它的作用是表明 <strong>该构造函数是显示的</strong>，而非隐式的（避免编译器自动隐式转换后调用函数），跟它相对应的另一个关键字是 implicit，意思是隐藏的，类构造函数默认情况下即声明为 implicit (隐式).</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">SmallInt si = 3;        // 正确：SmallInt 的构造函数不是显式的，可以隐式转换
// si + 3;              // 错误：此处需要隐式地类型转换，但 explicit 指出 operator int() const 操作必须为显式的
static&lt;int&gt;(si) + 3;    // 正确：显式地请求类型转换
</code></span></code></pre>
<p>但是存在一个例外，当表达式被用作条件， 编译器才会将显示的类型转换用于它，即就是，当表达式出现在以下的位置时，显示的类型转换被隐式执行：</p>
<ul>
<li>if、while及do语句的条件部分；</li>
<li>for语句头的条件表达式；</li>
<li>逻辑与或非运算符的运算对象；</li>
<li>条件运算符( ? : )的条件表达式。   </li>
</ul>
<h4 id="bool">转换 bool</h4>
<p>在标准库的早期版本中，IO 类型定义了向 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>void *</code></span> 的转换规则，以避免上面提到的问题。</p>
<p>在 C++11 新标准下，IO 标准库通过定义一个向 bool 的显示类型转换实现相同的目的。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">while (std::cin &gt;&gt; value);
</code></span></code></pre>
<p>当 cin 读完值后，由于在 while 的条件部分，因此显示的类型转换被隐式的执行，cin 转换为一个 bool 类型，用于判断是否读取成功。</p>
<h3 id="50-override-final">50. 虚函数的 override 和 final 指示符</h3>
<h4 id="override">override</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class Quote {
public:
    std::string isbn() const;
    virtual double net_price(std::size_t n) const;
    // const 给隐含的 this 指针加 const，表示这个 this 指向的对象是 const 的
    // 也就是说这个函数中无法改动数据成员了，相当于只读操作
}

class Bulk_quote : public Quote {
public:
    double net_price(std::size_t) const override; // 【 virtual 关键字非必须 】
    // C++11 允许派生类使用 override 显式的注明哪些成员函数需要被重写，如果没被重写，则编译器会报错。
    // double net_price(std::size_t) override; // 漏写了 const 编译器将报错
}

double print_total(ostream &amp;os, const Quote &amp;item, size_t n)
{
    // 根据传入 item 的对象类型调用
    // Quote::net_price 或者 Bulk_quote::net_price
    double ret = item.net_price(n);
    os &lt;&lt; &quot;ISBN:&quot; &lt;&lt; item.isbn(); // 调用 Quote::isbn
    return ret;
}

// 实际传入 print_total 的对象类型决定到底执行 net_price 的哪个版本
Quote quote;
Bulk_quote bulk;
print_total(cout, quote, 20);   // 调用：Quote::net_price
print_total(cout, bulk, 20);    // 调用：Bulk_quote::net_price
</code></span></code></pre>
<blockquote class="content-quote">
<p>https://www.cnblogs.com/xinxue/p/5471708.html</p>
<p><a href="https://blog.csdn.net/linuxwuj/article/details/83183381">C++11 override</a></p>
</blockquote>
<p>在成员函数声明或定义中， override 确保该函数为虚函数并覆写来自基类的虚函数。</p>
<p>位置：函数调用运算符之后，函数体或纯虚函数标识 &ldquo;= 0&rdquo; 之前。</p>
<p><strong>在派生类的成员函数中使用override时，如果基类中无此函数，或基类中的函数并不是虚函数，编译器会给出相关错误信息。</strong></p>
<h4 id="final">final 指示符用于防止继承的发生</h4>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">class NoDervied final { /* */ };        // final 指出 NoDervied 不能被继承【编译通过】
class Base { /* */ };                   // 【编译通过】
class Last final : Base { /* */ };      // final 指出 Last 不能被继承【编译通过】
// class Bad : NoDervied { /* */ };     // 错误：NoDervied 不能被继承
// class Bad2 : Last { /* */ };         // 错误：Last 不能被继承
</code></span></code></pre>
<h3 id="51">51. 删除的拷贝控制和继承</h3>
<h3 id="52">52. 继承的构造函数</h3>
<h3 id="53">53. 声明模板类型形参为友元</h3>
<h3 id="54">54. 模板类型别名</h3>
<h3 id="55">55. 模板函数的默认模板参数</h3>
<h3 id="56">56. 实例化的显式控制</h3>
<h3 id="57">57. 模板函数与尾置返回类型</h3>
<h3 id="58">58. 引用折叠规则</h3>
<h3 id="59-static_cast">59. 用 static_cast 将左值转换为右值</h3>
<h3 id="60-forward">60. 标准库 forward 函数</h3>
<h3 id="61">61. 可变参数模板</h3>
<p>一个 <strong>可变参数模板</strong> 就是一个接受可变数目参数的模板函数或模板类。</p>
<p>可变数目的参数被成为 <strong>参数包</strong>。</p>
<p>存在两种参数包：</p>
<ol>
<li>模板参数包，表示零个或多个模板参数；</li>
<li>函数参数包，表零个或多个函数参数。</li>
</ol>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">// Args 是一个模板参数包，rest 是一个函数参数包
// Args 表示零个或多个模板类型参数
// rest 表示零个或多个函数参数
template &lt;typename T, typename ... Args&gt;
void func(const T &amp;t, const Args &amp; ... rest); 
</code></span></code></pre>
<p>声明了 func 是一个可变参数函数模板，他有一个名为 T 的参数类型，和一个名为 Args 的模板参数包。这个包表示零个或多个额外的参数类型。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">int i = 0;
double d = 3.14;
string s = &quot;Hello&quot;;

func(i, s, 42, d);  // 包中有三个参数
func(s, 42, d);     // 包中有两个参数
func(42, d);        // 包中有两个参数
func(42);           // 包空
</code></span></code></pre>
<h3 id="62-sizeof">62. sizeof &hellip; 运算符</h3>
<p>当我们需要知道包中有多少元素时，可以使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>sizeof...</code></span>运算符。</p>
<pre><code class="pre-wrap"><span style="overflow-x: auto; max-width:100%; display:inline;"><code class="language-c++">template&lt;typename ... Args&gt; 
void g(Args ... args) {
    cout &lt;&lt; sizeof...(Args) &lt;&lt; endl;
    cout &lt;&lt; sizeof...(args) &lt;&lt; endl;
}
</code></span></code></pre>
<h3 id="63">63. 可变参数模板与转发</h3>
<h3 id="64-tuple">64. 标准库 tuple 类模板</h3>
<h3 id="65-bitset">65. 新的 bitset 运算</h3>
<h3 id="66">66. 正则表达式库</h3>
<h3 id="67">67. 随机数库</h3>
<h3 id="68">68. 浮点数格式控制</h3>
<h3 id="69-noexcept">69. noexcept 异常指示符</h3>
<h3 id="70-noexcept">70. noexcept 运算符</h3>
<h3 id="71">71. 内联命名空间</h3>
<h3 id="72">72. 继承的构造函数与多重继承</h3>
<h3 id="73-enum">73. 有作用域的 enum</h3>
<h3 id="74-enum">74. 说明类型用于保存enum 对象</h3>
<h3 id="75-enum">75. enum 的前置声明</h3>
<h3 id="76-mem_fn">76. 标准库 mem_fn 类模板</h3>
<h3 id="77-union">77. 类类型的 union 成员</h3>
</div>
<div id="nav">
  <div class="navigation">
  <ul class="pure-menu-list">
    <li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#1-long-long">1. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>long long</code></span> 数据类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#2">2. 列表初始化</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#3-constexpr">3. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 变量</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#4-constexpr">4. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#5-constexpr">5. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>constexpr</code></span> 构造函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#6-using">6. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>using</code></span> 类型别名</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#7-auto">7. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>auto</code></span> 类型说明符</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#8-decltype">8. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>decltype</code></span> 类型指示符</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#9-for">9. 范围 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>for</code></span> 语句</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#10">10. 类内初始值</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#11-vector">11. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>vector</code></span> 对象</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#12-const_interator-interator">12. 常量迭代器 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>const_interator</code></span> 类型和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>interator</code></span> 的返回值</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#13-auto-decltype">13. 使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>auto</code></span> 和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>decltype</code></span> 的简化声明</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#14-initializer_list">14. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>initializer_list</code></span> 形参</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#15">15. 列表初始化返回值</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#16">16. 使用尾置返回类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#17-default">17. 使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>= default</code></span> 显式生成默认构造函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#18">18. 委托构造函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#19-string">19. 用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>string</code></span> 对象处理文件名</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#20-cbegin-cend">20. 容器的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>cbegin</code></span> 和 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>cend</code></span> 函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#21-swap">21. 容器的非成员函数 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>swap</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#22-insert">22. 容器 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>insert</code></span> 成员的返回类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#23-emplace">23. 容器的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>emplace</code></span> 成员函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#24-shrink_to_fit">24. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>shrink_to_fit</code></span> 成员函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#25-string">25. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>string</code></span> 的数值转换函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#26-lambda">26. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 表达式</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#1-lambda">1. 向 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 传递参数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#2_1">2. 捕获列表</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 2.25em;" href="#_1">值捕获</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 2.25em;" href="#_2">引用捕获</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#27-lambda">27. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>lambda</code></span> 表达式中的尾置返回类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#28-bind">28. 标准库 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#1-check_size-sz">1. 绑定 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>check_size</code></span> 的 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>sz</code></span> 参数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#2-stdplaceholders">2. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::placeholders</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 2.25em;" href="#placeholders">使用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>placeholders</code></span> 名字</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 2.25em;" href="#bind">用 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>bind</code></span> 重拍参数顺序</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 2.25em;" href="#_3">绑定引用参数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 2.25em;" href="#2-stdis_placeholder">2. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::is_placeholder</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 2.25em;" href="#3-stdis_bind_expression">3. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>std::is_bind_expression</code></span></a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#29">29. 关联容器的初始化列表</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#30-pair">30. 列表初始化 <span style="overflow-x: auto; max-width:100%; display:inline;"><code>pair</code></span> 的返回类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#31-pair">31. <span style="overflow-x: auto; max-width:100%; display:inline;"><code>pair</code></span> 的列表初始化</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#32">32. 无序容器</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#395">管理桶 395</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#33">33. 智能指针</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#auto_ptr">auto_ptr</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#unique_ptr">unique_ptr</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#shared_ptr">shared_ptr</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#weak_ptr">weak_ptr</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#34">34. 动态分配对象</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#_4">列表初始化</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#auto">auto 和动态分配</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#const">动态分配 const 对象</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#35-for">35. 范围 for 语句不能以用于动态分配数组</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#36">36. 动态分配数组的列表初始化</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#37-auto">37. auto 不能用于分配数组</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#38-allocatoraonstruct">38. allocator::aonstruct 可以使用任意构造函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#39-default">39. 将 =default 用于拷贝控制成员</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#40-delete">40. 使用 =delete 阻止拷贝类对象</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#_5">析构函数不能是删除的成员</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#41">41. 用移动类对象代替拷贝类对象</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#42">42. 右值引用</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#_6">左值持有，右值短暂</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#43-move">43. 标准库 move 函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#44">44. 移动构造函数和移动赋值</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#45-noexcept">45. 移动构造函数通常应该是 noexcept</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#46">46. 移动迭代器</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#47">47. 引用限定成员函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#48-function">48. function 类模板</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#_7">不同类型可能具有相同的调用形式</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#function">重载的函数与 function</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#49-explicit">49. explicit 类型转换运算符</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#bool">转换 bool</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#50-override-final">50. 虚函数的 override 和 final 指示符</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#override">override</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.75em;" href="#final">final 指示符用于防止继承的发生</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#51">51. 删除的拷贝控制和继承</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#52">52. 继承的构造函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#53">53. 声明模板类型形参为友元</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#54">54. 模板类型别名</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#55">55. 模板函数的默认模板参数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#56">56. 实例化的显式控制</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#57">57. 模板函数与尾置返回类型</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#58">58. 引用折叠规则</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#59-static_cast">59. 用 static_cast 将左值转换为右值</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#60-forward">60. 标准库 forward 函数</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#61">61. 可变参数模板</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#62-sizeof">62. sizeof &hellip; 运算符</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#63">63. 可变参数模板与转发</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#64-tuple">64. 标准库 tuple 类模板</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#65-bitset">65. 新的 bitset 运算</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#66">66. 正则表达式库</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#67">67. 随机数库</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#68">68. 浮点数格式控制</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#69-noexcept">69. noexcept 异常指示符</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#70-noexcept">70. noexcept 运算符</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#71">71. 内联命名空间</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#72">72. 继承的构造函数与多重继承</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#73-enum">73. 有作用域的 enum</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#74-enum">74. 说明类型用于保存enum 对象</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#75-enum">75. enum 的前置声明</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#76-mem_fn">76. 标准库 mem_fn 类模板</a>
</li>
<li class="pure-menu-item">
  <a class="pure-menu-link" style="padding:0.1em 0em 0.1em 1.25em;" href="#77-union">77. 类类型的 union 成员</a>
</li>

  </ul>
</div>

</div>
 
    </div>
  </div>
  <div id="footer">
    <div class="legal pure-g">
  <div class="pure-u-1 u-sm-1-2">
    <p class="legal-license"><a href="https://beian.miit.gov.cn/#/Integrated/index">浙ICP备2020038748号</a></p>
  </div>
  <div class="pure-u-1 u-sm-1-2">
    <p class="legal-links"><a href="https://github.com/zromyk">GitHub</a></p>
    <p class="legal-copyright">Copyright © 2020 Wei Zhou. 保留所有权利。</p>
  </div>
</div>
  </div>
</body>
</html>
